package emulator.unittest.hardware.nmos6502.commands;

import org.junit.Before;
import org.junit.Test;

import emulator.EmulatorException;
import emulator.hardware.nmos6502.Flags6502;
import emulator.hardware.nmos6502.commands.ADC;

public class ADCTest extends CommandTestBase {
	@Before
	public void setUp()	{
		command = new ADC();
	}
	
	@Test
	public void testAddAllZero() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, 0, 0, 0, Flags6502.FLAG_ZERO, 0);
	}

	@Test
	public void testAddWithCarry() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_CARRY, 0, 0, 0, 1);
	}

	@Test
	public void testAddPositive() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, 0, 13, 0, 0, 13);
		executeAndCheckCommandOnAccu(command, 0, 13, 65, 0, 78);
		executeAndCheckCommandOnAccu(command, 0, 0, 73, 0, 73);
		executeAndCheckCommandOnAccu(command, 0, 27, 100, 0, 127);
		executeAndCheckCommandOnAccu(command, 0, 127, 128, Flags6502.FLAG_NEGATIVE, 255);
	}

	@Test
	public void testAddNegative() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, 0, 128, 127, Flags6502.FLAG_NEGATIVE, 255);
		executeAndCheckCommandOnAccu(command, 0, 250, 6, (Flags6502.FLAG_ZERO|Flags6502.FLAG_CARRY), 0);
		executeAndCheckCommandOnAccu(command, 0, 255, 1, (Flags6502.FLAG_ZERO|Flags6502.FLAG_CARRY), 0);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_CARRY, 254, 255, (Flags6502.FLAG_CARRY|Flags6502.FLAG_NEGATIVE), 254);
		executeAndCheckCommandOnAccu(command, 0, 255, 255, (Flags6502.FLAG_CARRY|Flags6502.FLAG_NEGATIVE), 254);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_CARRY, 128, 127, (Flags6502.FLAG_CARRY|Flags6502.FLAG_ZERO),	0);
	}

	@Test
	public void testAddSignedPositiveOverflow() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_CARRY, 0, 127, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_NEGATIVE), 128);
		executeAndCheckCommandOnAccu(command, 0, 1, 127, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_NEGATIVE), 128);
		executeAndCheckCommandOnAccu(command, 0, 127, 1, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_NEGATIVE), 128);
		executeAndCheckCommandOnAccu(command, 0, 127, 127, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_NEGATIVE),	254);
	}

	@Test
	public void testAddSignedNegativeOverflow() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, 0, 128, 128, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_CARRY|Flags6502.FLAG_ZERO), 0);
		executeAndCheckCommandOnAccu(command, 0, 150, 128, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_CARRY), 22);
		executeAndCheckCommandOnAccu(command, 0, 150, 150, (Flags6502.FLAG_OVERFLOW|Flags6502.FLAG_CARRY), 44);
	}
	
	@Test
	public void testDecimalModeFromZero() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL, 0, 0, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_ZERO, 0);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0, 0, Flags6502.FLAG_DECIMAL, 1);
	}

	@Test
	public void testDecimalModeOverflowNibbleToEmptyNibble() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL, 9, 1, Flags6502.FLAG_DECIMAL, 0x10);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 9, 0, Flags6502.FLAG_DECIMAL, 0x10);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0, 9, Flags6502.FLAG_DECIMAL, 0x10);
	}

	@Test
	public void testDecimalModeOverflowNibble() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL, 0x29, 1, Flags6502.FLAG_DECIMAL, 0x30);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x29, 0, Flags6502.FLAG_DECIMAL, 0x30);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x10, 0x19, Flags6502.FLAG_DECIMAL, 0x30);
	}

	@Test
	public void testDecimalModeOverflowOneToCarry() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL, 0x99, 1, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY|Flags6502.FLAG_ZERO, 0);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x99, 0, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY|Flags6502.FLAG_ZERO, 0);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x30, 0x69, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY|Flags6502.FLAG_ZERO, 0);
	}

	@Test
	public void testDecimalModeOverflowToCarry() throws EmulatorException
	{
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL, 0x99, 9, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 8);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x99, 0x31, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x31);
		executeAndCheckCommandOnAccu(command, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 0x37, 0x69, Flags6502.FLAG_DECIMAL|Flags6502.FLAG_CARRY, 7);
	}
}
